/**
 * 游戏逻辑
 * @author yxx0
 * 绑定场景 Canvas
 */

const PTM_RATIO = cc.PhysicsManager.PTM_RATIO;
const PSD_RADIUS = 2;

// 挖洞圆半径
const DIG_RADIUS = 50;
// 分块半径(小于挖洞)
const PICE_RADIUS = 30;
// 圆的边的数量
const DIG_FRAGMENT = 12;
// 归一到单位化
const DIG_OPTIMIZE_SIZE = 1;
//需要用水量
const NeedWaterNumber = 1000

import { liquidFunHandle } from "../liquidFunHandle";
import PhysicsPolygonColliderEx_piecewise from "../waterFlow/PhysicsPolygonColliderEx";

// require('./liquidfun');

const { ccclass, property } = cc._decorator;

@ccclass
export default class Game extends cc.Component {

    @property(cc.Node)
    node_dirty: cc.Node = null;

    @property(PhysicsPolygonColliderEx_piecewise)
    polyEx: PhysicsPolygonColliderEx_piecewise = null;





    @property(cc.Node)
    nodeBox: cc.Node = null;

    @property(cc.Node)
    nodeOut: cc.Node = null;

    @property(cc.Graphics)
    graphics: cc.Graphics = null;

    @property(cc.PhysicsBoxCollider)
    targetArea: cc.PhysicsBoxCollider = null;

    @property(cc.RigidBody)
    targetAreaR: cc.RigidBody = null;

    @property(cc.Animation)
    roleAnim: cc.Animation = null;


    @property(cc.Node)
    resetBtn: cc.Node = null;

    @property(cc.Label)
    Tips: cc.Label = null;


    private WaterUseNumber = 0;

    private graphicsw: cc.Graphics = null;

    private world: any = null;
    private canUpDate: boolean = false;

    private _role_state = -1;
    private m_winPane: cc.Node;

    onLoad(): void {
        const phyMgr = cc.director.getPhysicsManager();
        phyMgr.enabled = true;
        //phyMgr.debugDrawFlags = 7;


        this.m_winPane = this.node.getChildByName("winPane");
        this.m_winPane.active = false;

        this.createB2();
        // this.nodeBox.on("click", this.CreateWord, this)
        this.roleAnim.on('finished', this.onFinished, this);

        this.node_dirty.on(cc.Node.EventType.TOUCH_START, this._touchStart, this);
        this.node_dirty.on(cc.Node.EventType.TOUCH_MOVE, this._touchMove, this);
        this.node_dirty.on(cc.Node.EventType.TOUCH_END, this._touchEnd, this);
        this.node_dirty.on(cc.Node.EventType.TOUCH_CANCEL, this._touchEnd, this);

        this.resetBtn.on(cc.Node.EventType.TOUCH_START, this._touchreset, this);


        this.graphicsw = this.node_dirty.getComponent(cc.Mask)['_graphics'];
        this.WaterUseNumber = 0;
        setTimeout(() => {
            this.CreateWord();
        }, 1000);


    }

    _touchreset() {
        this.WaterUseNumber = 0;
        let particleCount = liquidFunHandle.Instance.MianparticleSystem.GetParticleCount();
        for (let i = 0; i < particleCount; ++i) {
            liquidFunHandle.Instance.MianparticleSystem.DestroyParticle(i);
        }

        liquidFunHandle.Instance.MianWorld.DestroyParticleSystem(liquidFunHandle.Instance.MianparticleSystem);
        cc.director.loadScene("game_water");
    }

    onDestroy(): void {

    }

    /**
     * 初始化
     */
    init(): void {
    }

    /**
     * 销毁
     */
    clear(): void {

    }

    /**
     * 初始化水源
     */
    private async createB2() {
        let gravity = new b2.Vec2(0, -10);    //重力值
        liquidFunHandle.Instance.InitMainWorld(gravity);


        var psd = new b2.ParticleSystemDef();
        psd.radius = 0.05;
        var particleSystem = liquidFunHandle.Instance.MianWorld.CreateParticleSystem(psd);
        liquidFunHandle.Instance.MianparticleSystem = particleSystem;

        this.scheduleOnce(() => { this.canUpDate = true }, 1)
    }

    lateUpdate(dt) {
        if (!liquidFunHandle.Instance.MianparticleSystem) return;
        liquidFunHandle.Instance.MianWorld.Step(dt, 8, 3, 3);
        let particleCount = liquidFunHandle.Instance.MianparticleSystem.GetParticleCount();
        let posBuff = liquidFunHandle.Instance.MianparticleSystem.GetPositionBuffer();


        let data = liquidFunHandle.Instance.MianparticleSystem.GetBodyContacts();
        let Contactsdata = liquidFunHandle.Instance.MianparticleSystem.GetContacts();

        for (let index = 0; index < data.length; index++) {
            const element = data[index];
            let itemContact = Contactsdata[index]
            if (itemContact.indexA == -1 || itemContact.indexB == -1) {
                continue
            }

            if (element && (element.body && element.body.body == this.targetAreaR) && element.index != -1) {
                liquidFunHandle.Instance.MianparticleSystem.DestroyParticle(element.index);
                this.WaterUseNumber++;
                this.Tips.string = `用水进度:${this.WaterUseNumber}/${NeedWaterNumber}`;
                //达到用水量后播放人们动画
                if (this.WaterUseNumber >= NeedWaterNumber) {
                    this.SetRoleStateAnim(2);
                } else {
                    this.SetRoleStateAnim(1);
                }
            }
        }
        const vertexes = [];

        this.graphics.clear();
        for (let i = 0; i < particleCount; ++i) {
            const x = posBuff[i].x * PTM_RATIO;
            const y = posBuff[i].y * PTM_RATIO;
            const pt = this.graphics.node.convertToNodeSpaceAR(cc.v2(x, y));
            // vertexes.push(pt);
            vertexes.push(cc.v2(x, y));
            const p2 = this.graphics.node.parent.convertToNodeSpaceAR(cc.v2(x, y))

            this.graphics.circle(p2.x, p2.y, PSD_RADIUS);
        }

        this.graphics.fill();
    }

    /**设置角色形象  0默认  1正在进水  2结束庆祝*/
    SetRoleStateAnim(state) {
        if (this._role_state == state) {
            return
        }
        this._role_state = state;
        let animnode = this.roleAnim
        switch (state) {
            case 0:
                let anim = animnode.play("anim");
                break;
            case 1:
                let anim_ing = animnode.play("anim_ing");
                //this.SetRoleStateAnim(0);
                break;
            case 2:
                let anim_end = animnode.play("anim_end");
                //获胜
                this.m_winPane.getComponent(cc.Animation).play("win");
                this.m_winPane.active = true;
                break;
            default:
                break;
        }
    }
    onFinished(type, state) {
        if (this._role_state == 1) {
            this.SetRoleStateAnim(0)
        }
    }


    CreateWord() {
        const box = new b2.PolygonShape();
        const pgd = new b2.ParticleGroupDef();
        box.SetAsBox(this.nodeBox.width / 2 / PTM_RATIO, this.nodeBox.height / 2 / PTM_RATIO);
        pgd.flags = b2.ParticleFlag.b2_waterParticle;
        // pgd.groupFlags = b2.ParticleGroupFlag.b2_solidParticleGroup;
        const pos = this.nodeBox.convertToWorldSpaceAR(cc.Vec2.ZERO).divSelf(PTM_RATIO);
        pgd.position.Set(pos.x, pos.y);
        // pgd.angle = -0.5;
        pgd.angularVelocity = Math.random() - 0.5;
        pgd.shape = box;
        // pgd.color.Set(0, 0, 255, 255);
        const particleGroup = liquidFunHandle.Instance.MianparticleSystem.CreateParticleGroup(pgd);
        // this.Tips.string = `用水进度:${this.WaterUseNumber}/100`;
        this.Tips.string = `用水进度:${this.WaterUseNumber}/${NeedWaterNumber}`;
    }
 
    start() {
        this.scheduleOnce(() => {
            this.reset();
            this.SetRoleStateAnim(0);
        }, 0.01);
    }

    private _rects: cc.Rect[] = [];
    reset() {
        this._rects = [];
        const polys: cc.Vec2[][][] = [];
        const totalRow = 12;
        const totalCol = 30;
        for (let index = 0; index < totalRow * totalCol; index++) {
            const row = Math.floor(index / totalCol);
            const col = index % totalCol;
            const y = row * PICE_RADIUS * 2 - totalRow * PICE_RADIUS;
            const x = col * PICE_RADIUS * 2 - totalCol * PICE_RADIUS;
            this._rects[index] = cc.rect(x, y, PICE_RADIUS * 2, PICE_RADIUS * 2);
            const { xMin, xMax, yMin, yMax } = this._rects[index];
            polys[index] = [[cc.v2(xMin, yMin), cc.v2(xMin, yMax), cc.v2(xMax, yMax), cc.v2(xMax, yMin)]]
        }
        this.polyEx.init(polys, this.graphicsw);
    }


    private _touchStart(touch: cc.Touch) {
        this._touchStartPos = undefined;
        this._touchMove(touch);
    }
    private _optimizePoint(point) {
        const x = Math.floor(point[0] * DIG_OPTIMIZE_SIZE) / DIG_OPTIMIZE_SIZE;
        const y = Math.floor(point[1] * DIG_OPTIMIZE_SIZE) / DIG_OPTIMIZE_SIZE;
        return cc.v2(x, y);
    }

    private _touchStartPos: cc.Vec2;
    private _touchMove(touch: cc.Touch) {
        const regions: cc.Vec2[] = [];
        const pos = this.graphics.node.convertToNodeSpaceAR(touch.getLocation());
        let xMin = Number.MAX_SAFE_INTEGER, xMax = Number.MIN_SAFE_INTEGER, yMin = Number.MAX_SAFE_INTEGER, yMax = Number.MIN_SAFE_INTEGER;
        const count = DIG_FRAGMENT;
        const regions_push = (x, y) => {
            const p = this._optimizePoint([x, y]);
            xMin = p.x < xMin ? p.x : xMin;
            yMin = p.y < yMin ? p.y : yMin;
            xMax = p.x > xMax ? p.x : xMax;
            yMax = p.y > yMax ? p.y : yMax;
            regions.push(p);
        }

        if (!this._touchStartPos) {
            for (let index = 0; index < count; index++) {
                const r = 2 * Math.PI * index / count;
                const x = pos.x + DIG_RADIUS * Math.cos(r);
                const y = pos.y + DIG_RADIUS * Math.sin(r);
                regions_push(x, y);
            }
            this._touchStartPos = pos;
        } else {
            const delta = pos.sub(this._touchStartPos);
            // 手指移动的距离太小的话忽略
            if (delta.lengthSqr() > 25) {
                // 这里是合并成一个顺滑的图形
                const startPos = this._touchStartPos;
                for (let index = 0; index < count; index++) {
                    const r = 2 * Math.PI * index / count;
                    let vec_x = DIG_RADIUS * Math.cos(r);
                    let vec_y = DIG_RADIUS * Math.sin(r);
                    let x, y;
                    if (delta.dot(cc.v2(vec_x, vec_y)) > 0) {
                        x = pos.x + vec_x;
                        y = pos.y + vec_y;
                    } else {
                        x = startPos.x + vec_x;
                        y = startPos.y + vec_y;
                    }
                    regions_push(x, y);
                }
                this._touchStartPos = pos;
            }
        }

        if (regions.length) {
            const rect_r = cc.Rect.fromMinMax(cc.v2(xMin, yMin), cc.v2(xMax, yMax));
            for (let index = 0; index < this._rects.length; index++) {
                const rect = this._rects[index];
                if (rect.intersects(rect_r)) {
                    this.polyEx.pushCommand('polyDifference', [regions, index])
                }
            }
        }
    }

    private _touchEnd(touch: cc.Touch) {
        this._touchStartPos = undefined;
    }


}
